package com.wisecoach.gatewayplus.utils;


import com.google.protobuf.InvalidProtocolBufferException;
import com.wisecoach.gatewayplus.transaction.lockedtx.TxRWSet;
import org.hyperledger.fabric.protos.common.Payload;
import org.hyperledger.fabric.protos.gateway.PreparedTransaction;
import org.hyperledger.fabric.protos.ledger.rwset.NsReadWriteSet;
import org.hyperledger.fabric.protos.ledger.rwset.TxReadWriteSet;
import org.hyperledger.fabric.protos.ledger.rwset.kvrwset.KVRWSet;
import org.hyperledger.fabric.protos.ledger.rwset.kvrwset.KVRead;
import org.hyperledger.fabric.protos.ledger.rwset.kvrwset.KVWrite;
import org.hyperledger.fabric.protos.peer.*;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * {@code @author:} wisecoach
 * {@code @date:} 2023/9/26 下午1:32
 * {@code @version:} 1.0.0
 */


public class TransactionUtils {
    private final static Set<String> nsToIgnore = new HashSet<>();

    static {
        nsToIgnore.add("_lifecycle");
    }

    public static TxRWSet resolveRWSet(org.hyperledger.fabric.client.Transaction transaction) {
        try {
            TxRWSet rwSet = new TxRWSet();
            Payload payload = Payload.parseFrom(PreparedTransaction.parseFrom(transaction.getBytes()).getEnvelope().getPayload());
            List<TransactionAction> actions = Transaction.parseFrom(payload.getData()).getActionsList();
            for (TransactionAction action : actions) {
                ChaincodeEndorsedAction endorsedAction = ChaincodeActionPayload.parseFrom(action.getPayload()).getAction();
                ChaincodeAction chaincodeAction = ChaincodeAction.parseFrom(ProposalResponsePayload.parseFrom(endorsedAction.getProposalResponsePayload()).getExtension());
                TxReadWriteSet txReadWriteSet = TxReadWriteSet.parseFrom(chaincodeAction.getResults());
                for (NsReadWriteSet nsReadWriteSet : txReadWriteSet.getNsRwsetList()) {
                    String ns = nsReadWriteSet.getNamespace();
                    if (nsToIgnore.contains(ns)) {
                        continue;
                    }
                    // 取得kv读写集
                    KVRWSet kvrwSet = KVRWSet.parseFrom(nsReadWriteSet.getRwset());
                    // 处理读集
                    HashSet<String> readKeySet = new HashSet<>();
                    List<KVRead> readsList = kvrwSet.getReadsList();
                    readsList.forEach(kvRead -> readKeySet.add(kvRead.getKey()));
                    rwSet.getReadSet().merge(ns, readKeySet, (oldValue, newValue) -> {
                        oldValue.addAll(newValue);
                        return oldValue;
                    });
                    // 处理写集
                    HashSet<String> writeKeySet = new HashSet<>();
                    List<KVWrite> writesList = kvrwSet.getWritesList();
                    writesList.forEach(kvWrite -> writeKeySet.add(kvWrite.getKey()));
                    rwSet.getWriteSet().merge(ns, writeKeySet, (oldValue, newValue) -> {
                        oldValue.addAll(newValue);
                        return oldValue;
                    });
                }
            }
            return rwSet;
        } catch (InvalidProtocolBufferException e) {
            throw new RuntimeException(e);
        }
    }
}
